package win.zxshuo.www.service;

import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.stereotype.Service;
import win.zxshuo.www.model.AuthorModel;
import win.zxshuo.www.model.BookCrawlerModel;
import win.zxshuo.www.model.BookModel;
import win.zxshuo.www.model.chapters.ChapterModel;
import win.zxshuo.www.repository.BookCrawlerRepository;
import win.zxshuo.www.repository.BookRepository;
import win.zxshuo.www.utils.StringUtils;

import java.util.*;

@Service
@Configurable
public class BookService {
    private Log logger = LogFactory.getLog(getClass());

    @Autowired
    BookRepository bookRepository;

    @Autowired
    AuthorService authorService;

    @Autowired
    CategoryService categoryService;

    @Autowired
    ChapterService chapterService;

    @Autowired
    BookCrawlerRepository bookCrawlerRepository;

    /**
      * @Description: 获取书籍使用的章节表值
      * @Author: RffanLAB
      * @Params: 
      * @Returns: 
      * @CreateDate: 2018/3/17
      */
    public Integer getBookChapterNum(Integer tableNum){
        return bookRepository.getBookNumByChapterTable(tableNum);
    }

    /**
      * @Description: 获取最高的章节表值
      * @Author: RffanLAB
      * @Params: 
      * @Returns: 
      * @CreateDate: 2018/3/17
      */
    public Integer getLatestChapterTable(){
        return bookRepository.getLatestChapterTable();
    }

    public boolean hasBook(String author,String book){
        List<BookModel> bookModels = bookRepository.getBookModelByAuthorName(author);
        if (bookModels.size() == 0){
            return false;
        }
        for (BookModel bookModel:bookModels){
            if (bookModel.getName().equals(book)){
                return true;
            }
        }
        return false;
    }

    /**
      * @Description: 添加书籍
      * @Author: RffanLAB
      * @Params: 
      * @Returns: 
      * @CreateDate: 2018/3/17
      */
    public BookModel addNewBook(String name,String surface,String category,String author,String introduction,Integer status,Double mark,String qidianurl) throws Exception{
        BookModel bookModel = new BookModel();
        System.out.println("name = [" + name + "], surface = [" + surface + "], category = [" + category + "], author = [" + author + "], introduction = [" + introduction + "], status = [" + status + "], mark = [" + mark + "], qidianurl = [" + qidianurl + "]");
        try {
            if (hasBook(author,name)){

                bookModel = bookRepository.findByNameAndAuthorModel(name,authorService.getAuthorBy(author));

                System.out.println(
                        bookModel instanceof BookModel
                );
            }else {
                bookModel.setCreateDate(new Date());
                bookModel.setModifyDate(new Date());
                bookModel.setName(name);
                bookModel.setSurface(surface);
                bookModel.setCategoryModel(categoryService.getCategoryByName(category));
                bookModel.setAuthorModel(authorService.getAuthorBy(author));
                bookModel.setIntroduction(introduction);
                bookModel.setChapterTable(chapterService.getAvailableChapterTable());
                bookModel.setStatus(status);
                bookModel.setMark(mark);
                bookModel.setGender(0);
                bookModel.setWordNum(0);
                bookModel.setQidianUrl(qidianurl);
                bookRepository.save(bookModel);
            }
        }catch (Exception e){
            logger.error(e.getMessage());
        }

        System.out.println(
                bookModel instanceof BookModel
        );
        return bookModel;
    }

    /**
     * @Description: 是不是这本书，用来判断采集获取的书籍目录页面是否正确的。
     * @param bookName
     * @param author
     * @return
     */
    public Boolean isTheBook(String bookName,String author){
        BookModel bookModel = bookRepository.findByNameAndAuthorModel(bookName,authorService.getAuthorBy(author));
        if (bookModel != null){
            return true;
        }
        return false;
    }

    /**
     * 通过书籍的名字和作者名字来获取书籍
     * @param bookName
     * @param author
     * @return
     */
    public BookModel getBookModelBy(String bookName,String author){
        return bookRepository.findByNameAndAuthorModel(bookName,authorService.getAuthorBy(author));
    }


    /**
     * 获取书籍的所有章节
     * @param bookid
     * @return
     */
    public List<List<ChapterModel>> getBookChapters(Long bookid){
        Optional<BookModel> bookModel = bookRepository.findById(bookid);
        if (bookModel.isPresent()){
            return chapterService.getAllChaptersBy(bookModel.get().getId(),bookModel.get().getChapterTable());
        }
        return null;
    }


    /**
     * 获取书籍模型
     * @param bookid
     * @return
     */
    public BookModel getBookById(Long bookid){
        Optional<BookModel> bookModel = bookRepository.findById(bookid);
        if (bookModel.isPresent()){
            return bookModel.get();
        }else {
            return null;
        }
    }

    /**
     * 获取所有在更新的书籍
     * @return
     */
    public List<BookModel> getAllBooksInUpdating(){
        return bookRepository.getAllBooksThatAreUpdating();
    }


    /**
     * 将一个巨量的数组分散多个给多线程用（预计书籍不会超过10万本，所以这个方法还是可行的，当数据超过50万本的时候请自行调整方法）
     * @param sepNum
     * @param bookModels
     * @return
     */
    public List<List<BookModel>> separateBookListBy(Integer sepNum,List<BookModel> bookModels){
        List<List<BookModel>> bookListsOfList = new ArrayList<>();
        List<BookModel> newBookModels = new ArrayList<>();
        Integer mark = 0;
        for (BookModel bookModel:bookModels){
            if (mark == (sepNum-1)){
                newBookModels.add(bookModel);
                bookListsOfList.add(newBookModels);
                newBookModels = new ArrayList<>();
                mark = 0;
            }else {
                newBookModels.add(bookModel);
                mark = mark + 1;
            }
        }
        return bookListsOfList;
    }


    /**
     * 获取最后一个章节表，以及章节表的使用次数
     */
    public Map<String,Integer> getLatestChapterTableInUseAndUseNum(){
        Map<String,Integer> results = new HashMap<>();
        List<Object[]> result = bookRepository.getLastChapterTableInUse();
        Integer tableNum = Integer.parseInt(String.valueOf(result.get(0)[0]));
        results.put("table",tableNum);
        results.put("num",Integer.parseInt(String.valueOf(result.get(0)[1])));
        return results;
    }


    public List<BookModel> getBooksByIds(String ids){
        List<Long> intIds = StringUtils.parseIdsToIntIds(ids);
        return bookRepository.getBooksByIds(intIds);
    }


    public void addBookWordNum(Integer wordNum,Long bookid){
        bookRepository.addWordnumForBook(bookid,wordNum);
    }

    /**
     * 获取所有需要更新的书籍
     * @return
     */
    public List<BookModel> getAllBookNeedsToUpdate(){
        List<BookModel>  bookModels = bookRepository.getAllBooksNeedToUpdate();
        return bookModels;
    }


    /**
     * 采集完成后更新记录
     * @param bookModel
     * @throws Exception
     */
    public void setBookCrawlerFinishedRecord(BookModel bookModel) throws Exception{
        if (bookModel == null){
            throw new Exception("在更新书籍采集条款的时候，传入的书籍不是为空，并不是一个有效的书籍");
        }
        BookCrawlerModel bookCrawlerModel = bookCrawlerRepository.getByBookid(bookModel.getId());
        if (bookCrawlerModel == null){
            bookCrawlerModel = new BookCrawlerModel();
            bookCrawlerModel.setCreateDate(new Date());
            bookCrawlerModel.setModifyDate(new Date());
            bookCrawlerModel.setFinished(bookModel.getStatus() == 1);
            bookCrawlerModel.setLastUpdated(new Date());
            bookCrawlerModel.setBookModel(bookModel);
            bookCrawlerModel.setFinishedBookFinishedCrawler(true);
        }else {
            bookCrawlerModel.setModifyDate(new Date());
            bookCrawlerModel.setLastUpdated(new Date());
            bookCrawlerModel.setFinishedBookFinishedCrawler(true);
        }
        bookCrawlerRepository.save(bookCrawlerModel);
    }


    public List<BookModel> searchBook(String booknameOrAuthor){
        List<BookModel> bookModels = bookRepository.findBookModelLike(booknameOrAuthor);
        return bookModels;
    }
}
